﻿using System;
using System.Collections.Generic;
using System.Data;
using Dune.Business.Domain;
using Dune.Common;
using Dune.Common.Services;
using Dune.Common.Utils;
using Dune.DAL.Common;
using Dune.DAL.Common.DALOperations;
using Dune.DAL.Common.SessionManagment;
using NHibernate;
using NHibernate.Expression;
using NHibernate.SqlCommand;
using NHibernate.Type;
using Expression = NHibernate.Expression.Expression;

namespace Dune.DAL.Managers
{
    public class BaseManager
    {

        protected ISession Session
        {
            get
            {
                return Locator.GetService<ISessionProvider>().GetSession();
            }
        }

        protected IDalOperation CreateSaveOperation()
        {
            // TODO check nested operations!!!
            return new SaveDalOperation(Session);
        }

        protected IDalOperation CreateSaveOperation(IsolationLevel level)
        {
            // TODO check nested operations!!!
            return new SaveDalOperation(Session, level);
        }

        protected IDalOperation CreateSaveOperation(FlushMode flushMode)
        {
            // TODO check nested operations!!!
            return new SaveDalOperation(Session, flushMode);
        }

        protected IDalOperation CreateLoadOperation()
        {
            // TODO check nested operations!!!
            return new LoadDalOperation();
        }

        protected void SetupFetchArgs(IQuery query, FetchOptions fetchOptions)
        {
            if (fetchOptions != null)
            {
                query.SetParameter("sortExpression", fetchOptions.SortExpression);
                query.SetParameter("sortDirection", fetchOptions.SortDirection);
                query.SetParameter("rowsFrom", fetchOptions.FirstResult);
                query.SetParameter("rowsTo", fetchOptions.FirstResult + fetchOptions.MaxResults - 1);
            }
        }

        protected void SetupFTSCriteria(ITextSearchSupported textSearchSupported, ICriteria criteria)
        {

            if (textSearchSupported == null)
                return;

            SetupFTSCriteria(textSearchSupported.GetText(), criteria);
        }

        protected void SetupFTSCriteria(string keyword, ICriteria criteria)
        {
            if (StringUtils.IsBlankOrNull(keyword))
                return;

            //            AbstractCriterion ftsCriteria = 
            //                NHibernate.Expression.Expression.Sql(
            //                    new SqlString("contains( {alias}.fts_text , ? )"),
            //                    keyword, 
            //                    TypeFactory.Basic("string"));
            //            keyword = '"' + keyword + '"';
            keyword = "\"*" + keyword + "*\"";


            AbstractCriterion ftsCriteria =
                NHibernate.Expression.Expression.Sql(
                    new SqlString("contains( {alias}.fts_text , ", Parameter.Placeholder, " )"),
                    keyword,
                    TypeFactory.Basic("string"));


            criteria.Add(ftsCriteria);

        }

        protected void SetupFTSCriteriaForView(string keyword, ICriteria criteria, string tableName, string tablePK, string viewPK)
        {
            if (StringUtils.IsBlankOrNull(keyword))
                return;

            //            keyword = '"' + keyword + '"';
            keyword = "\"*" + keyword + "*\"";


            AbstractCriterion ftsCriteria =
                NHibernate.Expression.Expression.Sql(
                    new SqlString("exists (select " + tablePK + " from " + tableName + " t " +
                                  "where t." + tablePK + " = {alias}." + viewPK + " and contains( t.fts_text , ", Parameter.Placeholder, " ))"),
                    keyword,
                    TypeFactory.Basic("string"));

            criteria.Add(ftsCriteria);

        }


        protected bool IsNewObject(object obj)
        {
            return !Session.Contains(obj) || Session.GetIdentifier(obj) == null;
        }

        protected ICriterion CreateOr(IList<ICriterion> criterions)
        {
            if (CollectionsUtils.IsEmpty(criterions))
                throw new ArgumentException("");

            if (criterions.Count == 1)
                return criterions[0];

            ICriterion accum = criterions[0];
            for (int i = 1; i < criterions.Count; i++)
            {
                accum = Expression.Or(accum, criterions[i]);
            }
            return accum;
        }
    }
}
